home *** CD-ROM | disk | FTP | other *** search
/ PC Media 7 / PC MEDIA CD07.iso / share / prog / cm / cmreserv.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-06  |  12.2 KB  |  459 lines

  1. // CmReserv.cpp
  2. // -----------------------------------------------------------------
  3. // Compendium - C++ Container Class Library
  4. // Copyright (C) 1992-1994, Glenn M. Poorman, All rights reserved
  5. // -----------------------------------------------------------------
  6. // In-memory data base implementation.
  7. // -----------------------------------------------------------------
  8.  
  9. #include <cm/include/cmreserv.h>
  10. #include <cm/include/cmobjref.h>
  11. #include <cm/include/cmarray.h>
  12. #include <cm/include/cmassoc.h>
  13. #include <cm/include/cmbag.h>
  14. #include <cm/include/cmbintr.h>
  15. #include <cm/include/cmdate.h>
  16. #include <cm/include/cmdeque.h>
  17. #include <cm/include/cmhdict.h>
  18. #include <cm/include/cmhash.h>
  19. #include <cm/include/cmordarr.h>
  20. #include <cm/include/cmqueue.h>
  21. #include <cm/include/cmring.h>
  22. #include <cm/include/cmset.h>
  23. #include <cm/include/cmstack.h>
  24. #include <cm/include/cmtime.h>
  25.  
  26.  
  27. // Declare and initialize the static class register list.
  28. CmLinkedList ___cmReserve_Register_List;
  29. CmLinkedList* CmReserve::_classes = &___cmReserve_Register_List;
  30.  
  31. // Initialize the references flag.  Setting this FALSE means that multiply
  32. // referenced objects will be written as such.  This can cause an I/O
  33. // performance hit so, if there are definately no multiply referenced
  34. // objects in the reserve, setting this to FALSE will greatly increase
  35. // I/O speed.
  36. Bool CmReserve::_references = TRUE;
  37.  
  38. // Declare and initialize the static reference table.
  39. CmBTree ___cmReserve_Reference_Table;
  40. CmBTree* CmReserve::_referenceTable = &___cmReserve_Reference_Table;
  41.  
  42.  
  43. // "CmReserve" is the reserve constructor.
  44. //
  45. CmReserve::CmReserve(const char* name)
  46. {
  47.   _name       = name;
  48.   _identifier = "CMRESERVE FILE";
  49.   _roots      = new CmBTreeDictionary;
  50. }
  51.  
  52.  
  53. // "CmReserve" is the reserve copy constructor.
  54. //
  55. CmReserve::CmReserve(const CmReserve& R)
  56. {
  57.   _name       = R._name;
  58.   _identifier = R._identifier;
  59.   _roots      = new CmBTreeDictionary(*(R._roots));
  60. }
  61.  
  62.  
  63. // "~CmReserve" is the reserve destructor.
  64. //
  65. CmReserve::~CmReserve()
  66. {
  67.   delete _roots;
  68. }
  69.  
  70.  
  71. // "=" assignment operator copies the entire contents of the specified
  72. // reserve into this reserve.
  73. //
  74. CmReserve& CmReserve::operator=(const CmReserve& R)
  75. {
  76.   if (&R != this)
  77.   {
  78.     delete _roots;
  79.     _name       = R._name;
  80.     _identifier = R._identifier;
  81.     _roots      = new CmBTreeDictionary(*(R._roots));
  82.   }
  83.   return *this;
  84. }
  85.  
  86.  
  87. // "exists" returns TRUE if the reserve file already exists on disk.
  88. //
  89. Bool CmReserve::exists() const
  90. {
  91.   return (CmReserveFile::exists((const char*) _name));
  92. }
  93.  
  94.  
  95. // "addRoot" adds the specified root label and root to the root list.
  96. //
  97. Bool CmReserve::addRoot(const char* name, CmContainer* pCont)
  98. {
  99.   if (!pCont) return FALSE;
  100.  
  101.   CmString temp(name);
  102.   if (_roots->contains(&temp)) return FALSE;
  103.   return _roots->add(new CmString(temp), pCont);
  104. }
  105.  
  106.  
  107. // "createRoot" creates a root container with the specified root name
  108. // and stuffs it into the root list.
  109. //
  110. CmContainer* CmReserve::createRoot(const char* name)
  111. {
  112.   CmContainer *pList = getRoot(name);
  113.   if (!pList)
  114.   {
  115.     pList = new CmLinkedList;
  116.     if (!pList) return NULL;
  117.     if (!_roots->add(new CmString(name), pList))
  118.     {
  119.       delete pList;
  120.       pList = NULL;
  121.     }
  122.   }
  123.   return pList;
  124. }
  125.  
  126.  
  127. // "totalRoots" returns the total number of roots.
  128. //
  129. int CmReserve::totalRoots() const
  130. {
  131.   return _roots->size();
  132. }
  133.  
  134.  
  135. // "containsRoot" checks if a root with the given name exists in
  136. // the reserve.
  137. //
  138. Bool CmReserve::containsRoot(const char* name) const
  139. {
  140.   return (getRoot(name)) ? TRUE : FALSE;
  141. }
  142.  
  143.  
  144. // "getRoot" finds the root at the given index in the root list and
  145. // returns a pointer to it.
  146. //
  147. CmContainer* CmReserve::getRoot(const char* name) const
  148. {
  149.   CmString temp(name);
  150.   return (CmContainer*) _roots->lookupObject(&temp);
  151. }
  152.  
  153.  
  154. // "removeRoot" removes and destroys the root with the specified
  155. // name in the root list.
  156. //
  157. Bool CmReserve::removeRoot(const char* name)
  158. {
  159.   CmString temp(name);
  160.   return _roots->remove(&temp);
  161. }
  162.  
  163.  
  164. // "removeAll" removes all roots from the reserve.
  165. //
  166. void CmReserve::removeAll()
  167. {
  168.   _roots->removeAll();
  169. }
  170.  
  171.  
  172. // "write" writes all the objects in the reserve to an output file
  173. // name with the reserve name.
  174. //
  175. Bool CmReserve::write() const
  176. {
  177.   CmReserveFile file((const char*) _name);              // Open the file.
  178.   if (!file) return FALSE;
  179.  
  180.   Bool success = file.write((const char*) _identifier); // Write identifier.
  181.   if (success) success = _roots->write(file);           // Write roots.
  182.   file.close();                                         // Close the file.
  183.   CmReserve::resetTable();
  184.   return success;
  185. }
  186.  
  187.  
  188. // "read" reads the file with the reserve name into the reserve.
  189. //
  190. Bool CmReserve::read()
  191. {
  192.   if (!exists()) return FALSE;              // Exit if no disk file.
  193.  
  194.   CmReserveFile file((const char*) _name);  // Open the file.
  195.   if (!file) return FALSE;
  196.  
  197.   char *ident = file.read();                // Read the identifier.
  198.   Bool success = (strcmp(ident, (const char*) _identifier) == 0);
  199.   delete[] ident;
  200.  
  201.   if (success)
  202.   {
  203.     removeAll();                            // Remove any existing roots.
  204.     success = _roots->read(file);           // Read roots.
  205.   }
  206.   file.close();                             // Close the file.
  207.   CmReserve::resetTable();
  208.   return success;
  209. }
  210.  
  211.  
  212. // "forEach" cycles through all objects in the reserve calling the
  213. // specified function for each object passing in the object pointer
  214. // and the application-supplied data.
  215. //
  216. void CmReserve::forEach(CmQueryFunc pFunc, void* pData)
  217. {
  218.   CmIterator *iterator = _roots->newIterator();
  219.   while (!iterator->done())
  220.   {
  221.     CmAssociation *pAssoc = (CmAssociation*) iterator->next();
  222.     CmContainer   *pCont  = (CmContainer*) pAssoc->object();
  223.     pCont->forEach(pFunc, pData);
  224.   }
  225. }
  226.  
  227.  
  228. // "forEach" cycles through all objects in the reserve calling the 
  229. // specified object member function for each object and passing in
  230. // the application-supplied data.
  231. //
  232. void CmReserve::forEach(CmQueryMemFunc pFunc, void* pData)
  233. {
  234.   CmIterator *iterator = _roots->newIterator();
  235.   while (!iterator->done())
  236.   {
  237.     CmAssociation *pAssoc = (CmAssociation*) iterator->next();
  238.     CmContainer   *pCont  = (CmContainer*) pAssoc->object();
  239.     pCont->forEach(pFunc, pData);
  240.   }
  241. }
  242.  
  243.  
  244. // "firstThat" returns the first object in the reserve that is
  245. // passed into the specified function and returns TRUE.
  246. //
  247. CmObject* CmReserve::firstThat(CmQueryFunc pFunc, void* pData)
  248. {
  249.   CmObject   *outObj   = NULL;
  250.   CmIterator *iterator = _roots->newIterator();
  251.   while (!iterator->done() && !outObj)
  252.   {
  253.     CmAssociation *pAssoc = (CmAssociation*) iterator->next();
  254.     CmContainer   *pCont  = (CmContainer*) pAssoc->object();
  255.     outObj = pCont->firstThat(pFunc, pData);
  256.   }
  257.   return outObj;
  258. }
  259.  
  260.  
  261. // "firstThat" returns the first object in the reserve that is
  262. // passed into the specified function and returns TRUE.
  263. //
  264. CmObject* CmReserve::firstThat(CmQueryMemFunc pFunc, void* pData)
  265. {
  266.   CmObject   *outObj   = NULL;
  267.   CmIterator *iterator = _roots->newIterator();
  268.   while (!iterator->done() && !outObj)
  269.   {
  270.     CmAssociation *pAssoc = (CmAssociation*) iterator->next();
  271.     CmContainer   *pCont  = (CmContainer*) pAssoc->object();
  272.     outObj = pCont->firstThat(pFunc, pData);
  273.   }
  274.   return outObj;
  275. }
  276.  
  277.  
  278. // "query" cycles through all objects in the reserve calling the
  279. // specified function for each object passing in the object pointer
  280. // and the application-supplied data.  A return value of TRUE from
  281. // the function means to add that object to the output object list.
  282. //
  283. CmContainer* CmReserve::query(CmQueryFunc pFunc, void* pData)
  284. {
  285.   CmLinkedList *pList    = new CmLinkedList;
  286.   CmIterator   *iterator = _roots->newIterator();
  287.   Bool          success  = TRUE;
  288.   while (!iterator->done() && success)
  289.   {
  290.     CmAssociation *pAssoc = (CmAssociation*) iterator->next();
  291.     CmContainer   *pCont  = (CmContainer*) pAssoc->object();
  292.     CmContainer   *temp   = pCont->query(pFunc, pData);
  293.     if (temp)
  294.     {
  295.       temp->ownsObjects(FALSE);
  296.       success = pList->addAllFrom(temp);
  297.       delete temp;
  298.     }
  299.     else
  300.       success = FALSE;
  301.   }
  302.   return pList;
  303. }
  304.  
  305.  
  306. // "query" cycles through all objects in the reserve calling the 
  307. // specified object member function for each object and passing in
  308. // the application-supplied data.  A return value of TRUE from the
  309. // function means to add that object to the output object list.
  310. //
  311. CmContainer* CmReserve::query(CmQueryMemFunc pFunc, void* pData)
  312. {
  313.   CmLinkedList *pList    = new CmLinkedList;
  314.   CmIterator   *iterator = _roots->newIterator();
  315.   Bool          success  = TRUE;
  316.   while (!iterator->done() && success)
  317.   {
  318.     CmAssociation *pAssoc = (CmAssociation*) iterator->next();
  319.     CmContainer   *pCont  = (CmContainer*) pAssoc->object();
  320.     CmContainer   *temp   = pCont->query(pFunc, pData);
  321.     if (temp)
  322.     {
  323.       temp->ownsObjects(FALSE);
  324.       success = pList->addAllFrom(temp);
  325.       delete temp;
  326.     }
  327.     else
  328.       success = FALSE;
  329.   }
  330.   return pList;
  331. }
  332.  
  333.  
  334. // "fileIdentifier" opens the specified file, reads the identifier
  335. // string, and returns it.  The application must delete the string.
  336. //
  337. char* CmReserve::fileIdentifier(const char* name)
  338. {
  339.   CmReserveFile file(name);
  340.   if (!file) return NULL;
  341.  
  342.   char *file_str = file.read();
  343.   file.close();
  344.   return file_str;
  345. }
  346.  
  347.  
  348. // "registerClass" registers the specified class object as "storable"
  349. // with the reserve.
  350. //
  351. Bool CmReserve::registerClass(CmObject* pObj)
  352. {
  353.   return (getClassRegister(pObj->isA())) ? FALSE : _classes->add(pObj);
  354. }
  355.  
  356.  
  357. // "getClassRegister" returns a pointer to the registered class of
  358. // the specified type.
  359. //
  360. CmObject* CmReserve::getClassRegister(const char* name)
  361. {
  362.   CmObject   *out      = NULL;
  363.   CmIterator *iterator = CmReserve::_classes->newIterator();
  364.   while (!iterator->done() && !out)
  365.   {
  366.     CmObject *pObj = iterator->next();
  367.     if (pObj->isA(name)) out = pObj;
  368.   }
  369.   delete iterator;
  370.   return out;
  371. }
  372.  
  373.  
  374. // "initialize" registers all of the Compendium object classes
  375. // with the reserve.
  376. //
  377. void CmReserve::initialize()
  378. {
  379.   registerClass(new CmArray);
  380.   registerClass(new CmAssociation(NULL, NULL));
  381.   registerClass(new CmBag);
  382.   registerClass(new CmBinaryTree);
  383.   registerClass(new CmBTree);
  384.   registerClass(new CmBTreeDictionary);
  385.   registerClass(new CmDate);
  386.   registerClass(new CmDeque);
  387.   registerClass(new CmHashDictionary);
  388.   registerClass(new CmHashTable);
  389.   registerClass(new CmLinkedList);
  390.   registerClass(new CmOrderedArray);
  391.   registerClass(new CmQueue);
  392.   registerClass(new CmRing);
  393.   registerClass(new CmSet);
  394.   registerClass(new CmStack);
  395.   registerClass(new CmString);
  396.   registerClass(new CmTime);
  397. }
  398.  
  399.  
  400. // "resetTable" resets the reference table.
  401. //
  402. void CmReserve::resetTable()
  403. {
  404.   CmReserve::_referenceTable->removeAll();
  405. }
  406.  
  407.  
  408. // "maintainReferences" sets the references flag.
  409. //
  410. void CmReserve::maintainReferences(Bool flag)
  411. {
  412.   CmReserve::_references = flag;
  413. }
  414.  
  415.  
  416. // "maintainReferences" returns the value of the references flag.
  417. //
  418. Bool CmReserve::maintainReferences()
  419. {
  420.   return CmReserve::_references;
  421. }
  422.  
  423.  
  424. // "addToTable" adds the specified object to the table.
  425. //
  426. Bool CmReserve::addToTable(CmObject* pObj, int policy)
  427. {
  428.   int ky = CmReserve::_referenceTable->size();
  429.   CmObjectReference *pR = new CmObjectReference(ky, pObj);
  430.   CmObjectReference::compareBy(policy);
  431.   return CmReserve::_referenceTable->add(pR);
  432. }
  433.  
  434.  
  435. // "getFromTable" returns the object in the table associated with the
  436. // specified key.
  437. //
  438. CmObject* CmReserve::getFromTable(int key)
  439. {
  440.   CmObjectReference::compareBy(CmObjectReference::KEYS);
  441.   CmObjectReference temp(key);
  442.   CmObjectReference* pR = (CmObjectReference*)
  443.                           CmReserve::_referenceTable->lookup(&temp);
  444.   return (pR) ? pR->object() : NULL;
  445. }
  446.  
  447.  
  448. // "getFromTable" returns the key in the table associated with the
  449. // specified object.
  450. //
  451. int CmReserve::getFromTable(CmObject *pObj)
  452. {
  453.   CmObjectReference::compareBy(CmObjectReference::OBJECTS);
  454.   CmObjectReference temp(pObj);
  455.   CmObjectReference* pR = (CmObjectReference*)
  456.                           CmReserve::_referenceTable->lookup(&temp);
  457.   return (pR) ? pR->key() : -1;
  458. }
  459.